package com.deer.wms.ware.task.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.deer.wms.base.system.dao.ErpBackRecordMapper;
import com.deer.wms.base.system.dao.ItemInfoMapper;
import com.deer.wms.base.system.model.*;
import com.deer.wms.base.system.model.Item.ItemErpBO;
import com.deer.wms.base.system.model.Item.ItemInfo;
import com.deer.wms.base.system.service.ItemInfoService;
import com.deer.wms.busine.tactic.model.RouteTactic;
import com.deer.wms.busine.tactic.model.RouteTacticCriteria;
import com.deer.wms.busine.tactic.service.RouteTacticService;
import com.deer.wms.intercept.common.data.CurrentUser;
import com.deer.wms.inventory.constant.InventoryConstant;
import com.deer.wms.inventory.model.Inventory.Inventory;
import com.deer.wms.inventory.model.Inventory.InventoryTransact;
import com.deer.wms.inventory.service.InventoryService;
import com.deer.wms.inventory.service.InventoryTransactService;
import com.deer.wms.project.root.core.result.CommonCode;
import com.deer.wms.project.root.core.service.QueryCriteria;
import com.deer.wms.project.root.exception.ServiceException;
import com.deer.wms.project.root.service.SuperServiceImpl;
import com.deer.wms.project.root.util.BeanUtils;
import com.deer.wms.project.root.util.DateUtils;
import com.deer.wms.project.root.util.HttpClient;
import com.deer.wms.review.manage.model.BillRecord;
import com.deer.wms.review.manage.service.BillRecordService;
import com.deer.wms.review.manage.service.CaseMasterService;
import com.deer.wms.system.manage.dao.CustomerMapper;
import com.deer.wms.system.manage.model.customer.Customer;
import com.deer.wms.system.manage.model.organization.Organization;
import com.deer.wms.system.manage.model.ware.WareInfo;
import com.deer.wms.system.manage.service.CustomerService;
import com.deer.wms.system.manage.service.OrganizationService;
import com.deer.wms.system.manage.service.ValidatorService;
import com.deer.wms.system.manage.service.WareInfoService;
import com.deer.wms.ware.task.constant.WareTaskConstant;
import com.deer.wms.ware.task.dao.SoDetailMapper;
import com.deer.wms.ware.task.dao.SoMasterMapper;
import com.deer.wms.ware.task.model.SO.CreateSo.CreateSo;
import com.deer.wms.ware.task.model.SO.CreateSo.CreateSoDeliveryAddress;
import com.deer.wms.ware.task.model.SO.CreateSo.CreateSoShippingAddress;
import com.deer.wms.ware.task.model.SO.CreateSo.CreateSoSkuDetail;
import com.deer.wms.ware.task.model.SO.*;
import com.deer.wms.ware.task.model.SO.vo.PickTaskVo;
import com.deer.wms.ware.task.model.SO.vo.SoDetailVo;
import com.deer.wms.ware.task.model.SO.vo.SoMasterVo;
import com.deer.wms.ware.task.model.pickTask.PickTask;
import com.deer.wms.ware.task.service.*;
import org.apache.http.HttpEntity;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.hibernate.type.descriptor.java.DataHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URISyntaxException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Created by guo on 2020/02/02.
 */
@Service
@Transactional
public class SoMasterServiceImpl extends SuperServiceImpl<SoMasterMapper, SoMaster> implements SoMasterService {

    @Autowired
    private SoMasterMapper soMasterMapper;

    @Autowired
    private ValidatorService validatorService;

    @Autowired
    private SoMasterService soMasterService;

    @Autowired
    private SoDetailService soDetailService;

    @Autowired
    private CaseMasterService caseMasterService;

    @Autowired
    private SoMasterFileService soMasterFileService;

    @Autowired
    private SoDetailFileService soDetailFileService;
    @Autowired
    private RouteTacticService routeTacticService;

    @Autowired
    private BillRecordService billRecordService;
    @Autowired
    private InventoryService inventoryService;
    @Autowired
    private InventoryTransactService inventoryTransactService;
    @Autowired
    private PickTaskService pickTaskService;
    @Autowired
    private SoDetailMapper soDetailMapper;
    @Autowired
    private ErpBackRecordMapper erpBackRecordMapper;
    @Autowired
    private CustomerMapper customerMapper;
    @Autowired
    private ItemInfoMapper itemInfoMapper;
    @Autowired
    private CustomerService customerService;


    @Override
    public List<SoMasterDto> findList(SoMasterCriteria criteria) {
        return soMasterMapper.findList(criteria);
    }

    @Override
    public List<SoMasterDto> findByWaveId(Integer id, Integer wareId) {
        return soMasterMapper.findByWaveId(id, wareId);
    }


    @Override
    public SoMasterDto getSeedingByItemCode(String itemCode, Integer wareId, Integer waveMasterId) {
        List<SoMasterDto> list = soMasterMapper.getSeedingByItemCode(itemCode, wareId, waveMasterId);
        if (list.size() > 0) {

            return list.get(0);
        } else {
            return null;
        }
    }


    @Override
    public void deleteByBillNo(String billNo) {
        soMasterMapper.deleteByBillNo(billNo);
    }


    @Override
    public void createSoMaster(SoData soData, CurrentUser currentUser) {
        /**
         *  新建SO单据
         */
        SoMaster soMaster = soData.getSoMaster();
        String tableName = "so_master";
        Integer nextId = validatorService.getNextId(tableName);

        String billNo = "SO" + "-" + nextId;
        Integer createUserId = currentUser.getUserId();
        String createUserName = currentUser.getUserName();
        String createTime = DateUtils.getNowDateTimeString();

        if (soData.getBillSource() == 1 || soData.getBillSource() == 3 || soData.getBillSource() == 4) {
            //状态    2-等待审核(初始化)  1-审核通过  0-审核中  -1-审核退回
            Integer state = 1;

            if (soData.getInsertType() == -2) {
                //草稿
                state = 1;
            } else if (soData.getInsertType() == 0) {
                //正式提交
                String billNo1 = soData.getSoMaster().getBillNo();
                //通过草稿提交，则需要先把草稿删掉
                if (billNo1 != null) {
                    soMasterService.deleteByBillNo(billNo1);
                }
                /**
                 * 添加审核流
                 */
                //        -1不通过  0-流转中 1-已通过
                state = caseMasterService.createCase(billNo, 3, currentUser.getUserId(), soMaster.getWareId(), soMaster.getOrganizationId());
            }

            soMaster.setCreateUserId(createUserId);
            soMaster.setCreateUserName(createUserName);
            soMaster.setCreateTime(createTime);
            soMaster.setBillNo(billNo);
            soMaster.setCaseState(state);
            soMaster.setInsertType(soData.getInsertType());
            soMaster.setBillSource(soData.getBillSource());
            soMaster.setSoStructure(soData.getSoDetails().size());
            soMasterService.save(soMaster);


            List<SoDetail> soDetails = soData.getSoDetails();
            for (int i = 0; i < soDetails.size(); i++) {
                String detailNo = billNo + "-" + (i + 1);
                SoDetail soDetail = soDetails.get(i);
                soDetail.setBillNo(billNo);
                soDetail.setDetailNo(detailNo);
                soDetail.setState(0);
                soDetailService.save(soDetail);
            }
        }
    }

    @Override
    public void createFile(String billNo, CurrentUser currentUser) {
        SoMaster soMaster = this.findBy("bill_no", billNo);
        //状态为 ASN完成状态
        Integer fileUserId = currentUser.getUserId();
        String fileUserName = currentUser.getUserName();
        String fileTime = DateUtils.getNowDateTimeString();
        if (soMaster.getState() != 10) {
            throw new ServiceException(CommonCode.SO_FILE_ERROR);
        }
        BillRecord billRecord = new BillRecord();
        billRecord.setBillNo(billNo);
        billRecord.setRecordType(26);//SO归档
        billRecord.setCreateTime(fileTime);
        billRecord.setCreateUserId(fileUserId);
        billRecord.setCreateUserName(fileUserName);
        billRecordService.createBillRecord(billRecord, currentUser);

        SoMasterFile soMasterFile = new SoMasterFile();
        BeanUtils.copyProperties(soMaster, soMasterFile);

        soMasterFile.setFileUserId(fileUserId);
        soMasterFile.setFileUserName(fileUserName);
        soMasterFile.setFileTime(fileTime);
        soMasterFileService.save(soMasterFile);

        List<SoDetail> soDetails = soDetailService.findByBillNo(billNo);

        for (int i = 0; i < soDetails.size(); i++) {

            SoDetail soDetail = soDetails.get(i);
            SoDetailFile soDetailFile = new SoDetailFile();
            BeanUtils.copyProperties(soDetail, soDetailFile);

            soDetailFileService.save(soDetailFile);


        }
        soMasterService.deleteByBillNo(billNo);
        BillRecord billRecord1 = billRecordService.findByBillNoAndType(billNo, 26);//SO归档
        billRecord1.setModifyUserId(fileUserId);
        billRecord1.setModifyUserName(fileUserName);
        billRecord1.setModifyTime(DateUtils.getNowDateTimeString());
        billRecordService.updateById(billRecord1);
    }

    @Override
    public SoMaster findBy(String fileName, String value) {
        QueryWrapper<SoMaster> qw = new QueryWrapper<>();
        return this.getOne(qw.eq(fileName, value));
    }

    @Override
    public void sendOut(SoMaster soMaster, CurrentUser currentUser) {
        //Step1.生成库存事务
        List<PickTask> pickTasks = pickTaskService.findBySoMasterId(soMaster.getSoMasterId());
        for (PickTask pickTask : pickTasks) {
            toStockRequest(pickTask, currentUser);
        }

        //Step2.扣减库存
        inventoryService.sendOut(soMaster.getBillNo(), soMaster.getWareId());

        //Step3.回写单据状态
        soMaster.setState(WareTaskConstant.SO_STATE_OUTED);
        soMaster.setOutTime(DateUtils.getNowDateTimeString());
        soMaster.setOutUserId(currentUser.getUserId());
        soMaster.setOutUserName(currentUser.getUserName());
//        soMaster.setWeight(weight);
        soMasterService.updateById(soMaster);
        List<SoDetail> soDetails = soDetailService.findByBillNo(soMaster.getBillNo());
        for (SoDetail soDetail : soDetails) {
            soDetail.setDeliveryQuantity(soDetail.getOrderQuantity());
            soDetail.setState(WareTaskConstant.SO_DETAIL_STATE_ALL_SEND);
        }
        soDetailService.updateBatchById(soDetails);

        for (PickTask pickTask : pickTasks) {
            pickTask.setSeededQuantity(pickTask.getPickQuantity());
            pickTask.setState(WareTaskConstant.PICK_STATE_OUTED);
        }
        pickTaskService.updateBatchById(pickTasks);
    }

    private InventoryTransact toStockRequest(PickTask pickTask, CurrentUser currentUser) {
        InventoryTransact inventoryTransact = new InventoryTransact();
        //Step1.准备数据
        //仓库
        inventoryTransact.setWareId(pickTask.getWareId());
        inventoryTransact.setWareName(pickTask.getWareName());
        //货主
        inventoryTransact.setToOrganizationId(pickTask.getOrganizationId());
        inventoryTransact.setToOrganizationName(pickTask.getOrganizationName());
        //库位
        inventoryTransact.setFromCellCode(pickTask.getCellCode());
        //容器
        inventoryTransact.setFromBoxCode(pickTask.getBoxCode());
        //物料
        inventoryTransact.setItemCode(pickTask.getItemCode());
        inventoryTransact.setItemName(pickTask.getItemName());
        inventoryTransact.setImgUrl(pickTask.getImgUrl());
        //批次
        inventoryTransact.setFromBatchId(pickTask.getBatchId());
        inventoryTransact.setFromBatchName(pickTask.getBatchName());
        //数量
        inventoryTransact.setFromQuantity(pickTask.getPickQuantity());
        //包装 转换率
        inventoryTransact.setFromPackDetailId(pickTask.getPackDetailId());
        inventoryTransact.setFromPackDescribe(pickTask.getPackDescribe());
        //创建人 时间
        inventoryTransact.setCreateUserId(currentUser.getUserId());
        inventoryTransact.setCreateUserName(currentUser.getUserName());
        inventoryTransact.setCreateTime(DateUtil.now());
        //事务类型
        inventoryTransact.setTransactType(InventoryConstant.INVENTORY_TYPE_OUT);
        //来源单据号
        inventoryTransact.setBillNo(pickTask.getPickTaskCode());

        //Step2.保存，返回
        inventoryTransactService.save(inventoryTransact);
        return inventoryTransact;
    }

    @Override
    public List<SoMaster> findSoGroupInfo(SoMasterCriteria criteria) {
        return soMasterMapper.findSoGroupInfo(criteria);
    }

    @Override
    public List<SoMaster> findSoByWave(SoMasterCriteria criteria) {
        return soMasterMapper.findSoByWave(criteria);
    }

    @Override
    public Integer findCountByWaveIdAndState(Integer waveMasterId, Integer state) {
        return soMasterMapper.findCountByWaveIdAndState(waveMasterId, state);
    }


    @Override
    public List<SoMaster> findCanTongBu() {
        return soMasterMapper.findCanTongBu();
    }

    @Override
//    public void setCarriersWithRouteTactic(Integer organizationId, Integer wareId) {
    public void setCarriersWithRouteTactic() {
        SoMasterCriteria soMasterCriteria = new SoMasterCriteria();
//        soMasterCriteria.setOrganizationId(organizationId);
//        soMasterCriteria.setWareId(wareId);
        List<SoMasterDto> soMasters = soMasterMapper.findThatNoCarrier(soMasterCriteria);
        RouteTacticCriteria criteria = new RouteTacticCriteria();
//        criteria.setOrganizationId(organizationId);
//        criteria.setWareId(wareId);
        criteria.setState(1);
        List<RouteTactic> routeTactics = routeTacticService.findList(criteria);
        if (routeTactics.size() == 0) {
            throw new ServiceException(CommonCode.NO_ROUTE_TACTIC);
        }

        for (SoMasterDto soMaster : soMasters) {
            Double weight = soMaster.getWeight();
            Double size = soMaster.getSize();
            tacticLoop:
            for (RouteTactic routeTactic : routeTactics) {
                Double maxWeight = routeTactic.getMaxWeight();
                Double minWeight = routeTactic.getMinWeight();
                Double maxSize = routeTactic.getMaxSize();
                Double minSize = routeTactic.getMinSize();
                if (weight > minWeight && weight < maxWeight && size > minSize && size < maxSize) {
                    soMaster.setCarrierId(routeTactic.getCarrierId());
                    soMaster.setCarrierName(routeTactic.getCarrierName());
                    soMasterService.updateById(soMaster);
                    break tacticLoop;
                }
            }
        }
    }

    @Override
    public List<PdaSearchSoData> pdaSearchSo(String trackCode) {
        return soMasterMapper.pdaSearchSo(trackCode);
    }

    @Override
    public SoMasterYdyp getYdyp(String itemCode, Integer wareId, Integer waveId) {
        return soMasterMapper.getYdyp(itemCode, wareId, waveId);
    }

    @Override
    public SoMasterYdyp getYdyp2(String itemCode, Integer wareId, Integer waveId) {
        return soMasterMapper.getYdyp2(itemCode, wareId, waveId);
    }


    @Autowired
    private WareInfoService wareInfoService;
    @Autowired
    private ItemInfoService itemInfoService;
    @Autowired
    private OrganizationService organizationService;

    @Override
    public void createSO(CreateSo createSo, CurrentUser currentUser) {
        SoMaster soMaster = soMaster = this.findBy("bill_no", createSo.getBillNo());
        if (soMaster != null) {
            throw new ServiceException(CommonCode.BILL_NO, "");
        }
        soMaster = new SoMaster();
        if (createSo.getWareCode() == null) {
            throw new ServiceException(CommonCode.WARE_NULL, "");
        }
        if (createSo.getOrgCode() == null) {
            throw new ServiceException(CommonCode.ORG_NULL, "");
        }

        String billNo = createSo.getBillNo();
        Integer createUserId = currentUser.getUserId();
        String createUserName = currentUser.getUserName();
        String createTime = DateUtils.getNowDateTimeString();
        String wareCode = createSo.getWareCode();
        String orgCode = createSo.getOrgCode();
        WareInfo wareInfo = wareInfoService.getOneByField("ware_code", wareCode);
        Organization organization = organizationService.findBy("organizationCode", orgCode);

        if (createSo.getOrderTime() == null || createSo.getOrderTime().equals("")) {
            throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "下单时间不得为空");
        }

        if (wareInfo == null) {
            throw new ServiceException(CommonCode.WARE_NULL, "");
        }
        if (organization == null) {
            throw new ServiceException(CommonCode.ORG_NULL, "");
        }
        Integer state = 2;
        // state = caseMasterService.createCase(billNo, 2, currentUser.getUserId(), wareInfo.getWareId(),organization.getOrganizationId());

        soMaster.setState(state);
        soMaster.setBillNo(billNo);
        soMaster.setCreateTime(createTime);
        soMaster.setCreateUserId(createUserId);
        soMaster.setCreateUserName(createUserName);
        soMaster.setWareId(wareInfo.getWareId());
        soMaster.setWareName(wareInfo.getWareName());
        soMaster.setWareId(wareInfo.getWareId());
        soMaster.setWareCode(wareInfo.getWareCode());
        soMaster.setOrganizationCode(organization.getOrganizationCode());
        soMaster.setOrganizationName(organization.getOrganizationName());
        soMaster.setOrganizationId(organization.getOrganizationId());
        soMaster.setAllotBillNo(createSo.getBillNo());
        soMaster.setShipCode(createSo.getShipCode());
        soMaster.setShipBillCode(createSo.getShipBillCode());
        soMaster.setExpressBillUrl(createSo.getExpressBillUrl());
        soMaster.setInsertType(4);
        soMaster.setOrderTime(createSo.getOrderTime());

        CreateSoShippingAddress shippingAddress = createSo.getShippingAddress();
        soMaster.setShipLinkMan(shippingAddress.getLinkMan());
        soMaster.setShipLinkPhone(shippingAddress.getLinkPhone());
        soMaster.setShipCity(shippingAddress.getCity());
        soMaster.setShipCountry(shippingAddress.getCountry());
        soMaster.setShipProvince(shippingAddress.getProvince());
        soMaster.setShipArea(shippingAddress.getArea());
        soMaster.setShipDetailAddress(shippingAddress.getDetailAddress());

        CreateSoDeliveryAddress deliveryAddress = createSo.getDeliveryAddress();
        soMaster.setLinkMan(deliveryAddress.getLinkMan());
        soMaster.setLinkPhone(deliveryAddress.getLinkPhone());
        soMaster.setProvince(deliveryAddress.getProvince());
        soMaster.setCity(deliveryAddress.getCity());
        soMaster.setCountry(deliveryAddress.getCountry());
        soMaster.setArea(deliveryAddress.getArea());
        soMaster.setDetailAddress(deliveryAddress.getDetailAddress());
        soMaster.setCountry(deliveryAddress.getCountry());


        soMaster.setLastMileDestination(createSo.getLastMileDestination());
        soMaster.setLastMileLineCode(createSo.getLastMileLineCode());
        soMaster.setLastMileSortingCode(createSo.getLastMileSortingCode());
        soMaster.setSoUdfHs1(createSo.getExt1());
        soMaster.setSoUdfHs2(createSo.getExt2());
        soMaster.setSoUdfHs3(createSo.getExt3());
        soMaster.setSoStructure(createSo.getSoSkuDetails().size());
        soMaster.setTotalPrice(createSo.getCodValue());
        soMaster.setTradeNo(createSo.getTradeNo());
        soMaster.setShop(createSo.getShop());
        soMasterService.save(soMaster);


        List<CreateSoSkuDetail> asnskuDetails = createSo.getSoSkuDetails();
        for (int i = 0; i < asnskuDetails.size(); i++) {
            CreateSoSkuDetail createSoSkuDetail = asnskuDetails.get(i);

            SoDetail soDetail = new SoDetail();
            soDetail.setBillNo(soMaster.getBillNo());
            soDetail.setDetailNo(soMaster.getBillNo() + (i + 1));
            soDetail.setItemCode(createSoSkuDetail.getSkuCode());

            if (createSoSkuDetail.getSkuCode() == null || createSoSkuDetail.getSkuCode().trim().equals("")) {
                throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "SKU无效");
            }
            ItemInfo itemInfo = itemInfoService.findBy("item_code", createSoSkuDetail.getSkuCode());
            if (itemInfo == null) {
                itemInfo = new ItemInfo();
                itemInfo.setImgUrl(createSoSkuDetail.getImgUrl());
                itemInfo.setItemCode(createSoSkuDetail.getSkuCode());
                itemInfo.setItemName(createSoSkuDetail.getSkuName());
                itemInfo.setPackCode("sys_pack");
                itemInfoService.save(itemInfo);
            }
            soDetail.setItemName(itemInfo.getItemName());
            soDetail.setSpec(itemInfo.getSpec());
            soDetail.setModel(itemInfo.getModel());
            soDetail.setImgUrl(itemInfo.getImgUrl());
            soDetail.setPackDetailId(166);
            soDetail.setTransRatio(1.0);
            soDetail.setPackDescribe("each");
            soDetail.setOrderQuantity(createSoSkuDetail.getQuantity());
            soDetailService.save(soDetail);
        }
    }

    @Override
    public Integer getMaxPriority() {
        return soMasterMapper.getMaxPriority();
    }

    @Override
    public void updatePriority(Integer soMasterId, Integer priority) {
        soMasterMapper.updatePriority(soMasterId, priority);
    }



    //去重出库表
    public List<BillOutBO> filterBillOut(List<BillOutBO> billOutBOS, Set<String> billNo) {
        return billOutBOS.stream().filter(item -> !billNo.contains(item.getBillNo())).collect(Collectors.toList());
    }


    //去重出库详情表
    public List<BillOutDetailBO> filterDetaiBo(List<BillOutDetailBO> billOutDetailBOS, Set<String> billNo) {
        return billOutDetailBOS.stream().filter(item -> !billNo.contains(item.getBillNo())).collect(Collectors.toList());
    }

    public List<BillOutDetailBO> insertBillNo(BillOutBO billOutBO) {
        List<BillOutDetailBO> billOutDetail = billOutBO.getDetails();
        return billOutDetail.stream().map(
                item -> {
                    item.setSupplierName(billOutBO.getSupplierName());
                    item.setBillNo(billOutBO.getBillNo());
                    item.setOrderBillNo(billOutBO.getOrderBillNo());
                    item.setSourceBillId(billOutBO.getOrderBillId());

                    return item;
                }
        ).collect(Collectors.toList());
    }

//
//    public List<BillOutDetailBO> getAllBillOut(List<BillOutDetailBO> list) {
//
//    }

    public Double sumSoQty(List<BillOutDetailBO> list, String billNo) {
     return    list.stream().filter(item -> item.getBillNo().equals(billNo)).mapToDouble(BillOutDetailBO::getQty).sum();
    }
  public Double sumQcQty(List<BillOutDetailBO> list, String billNo) {
      return list.stream().filter(item -> item.getBillNo().equals(billNo)).mapToDouble(BillOutDetailBO::getQcQty).sum();
    }

    @Override
    public String saveBillOutInfo() {
        Integer wareId = 285;
        List<WareInfo> wareInfoList = wareInfoService.list();
        Map<Integer, List<WareInfo>> wareMap = wareInfoList.stream().collect(Collectors.groupingBy(WareInfo::getWareId));

        try {
            //请求token
            System.out.println("请求token");
            MultiValueMap<String, String> stringMultiValueMap = new LinkedMultiValueMap<>();
            stringMultiValueMap.add("client_id", "KingdeeK3_Rggy_AppClient_Test");
            stringMultiValueMap.add("client_secret", "TekE%dAISMCvwk7V");
            stringMultiValueMap.add("grant_type", "password");
            stringMultiValueMap.add("username", "epichust");
            stringMultiValueMap.add("password", "hK@vmz0YI1e^thtB");
            String tokenUrl = "https://syecrg.sieyuan.com:44310/connect/token";
            String clientRg = HttpClient.clientRg(tokenUrl, HttpMethod.POST, stringMultiValueMap);
            JSONObject jsonObject = JSONObject.parseObject(clientRg);
            String token = jsonObject.getString("access_token");
            System.out.println("token" + token);

            if (token != null) {

                Map<String, String> map1 = new HashMap<>();
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(new Date());
//                calendar.add(Calendar.DAY_OF_MONTH,-3);
                map1.put("dateFrom", new SimpleDateFormat("yyyy-MM-dd").format(calendar.getTime()));
                map1.put("dateFrom", "2022-05-25");

                //调用erp接口获取数据
                CloseableHttpClient client = HttpClients.createDefault();
                URIBuilder uriBuilder = new URIBuilder("https://syecrg.sieyuan.com:44398/api/Epichust/GetAllIMOutSourceBills");
                HttpPost post = new HttpPost(uriBuilder.build());
                StringEntity myEntity = new StringEntity(JSON.toJSONString(map1), "UTF-8");// 构造请求数据
                post.setHeader("Content-Type", "application/json");
                post.addHeader("Authorization", "Bearer " + token);
                post.setEntity(myEntity);// 设置请求体
                String responseContent = null; // 响应内容
                CloseableHttpResponse response = null;
                try {
                    response = client.execute(post);
                    HttpEntity entity = response.getEntity();
                    if (response.getStatusLine().getStatusCode() == 200) {
                        String content = EntityUtils.toString(entity, "UTF-8");
                        //订单数量
                        List<BillOutBO> po = (List<BillOutBO>) JSON
                                .parseArray(content, BillOutBO.class);
                        //获取所有详情信息

                        List<SoMaster> soMasters = new ArrayList<>();
                        List<SoDetail> soDetailList = new ArrayList<>();
                        List<BillOutDetailBO> billOutDetailBOS = new ArrayList<>();
                        po.stream().map(item -> {
                            item.setDetails(insertBillNo(item));
                            billOutDetailBOS.addAll(item.getDetails());
                            return item;
                        }).collect(Collectors.toList());
                        //单号去重

                        Set <String> oldBillNos = po.stream().map(BillOutBO::getBillNo).collect(Collectors.toSet());

                        //获取订单中所有的数据
                        List<SoMaster> soMasterList = soMasterService.list(new QueryWrapper<SoMaster>().in("bill_no", oldBillNos));
                        Set<String> newBillNos = soMasterList.stream().map(SoMaster::getBillNo).collect(Collectors.toSet());
                        //不包含单号的数据
                        List<BillOutBO> billOutBOS = this.filterBillOut(po, newBillNos);
                        List<BillOutDetailBO> billOutDetailBOS1 = filterDetaiBo(billOutDetailBOS, newBillNos);
                        if (ObjectUtil.isEmpty(billOutBOS) && ObjectUtil.isEmpty(billOutDetailBOS1)) {
                            return null;
                        }
                        Set<String> itemNumbers = billOutDetailBOS1.stream().map(BillOutDetailBO::getItemNumber).collect(Collectors.toSet());
                        //获取所有物料
                        List<ItemInfo> itemInfoList = itemInfoService.list(new QueryWrapper<ItemInfo>().in("item_code", itemNumbers));
                        //新增详情
                        for (BillOutDetailBO billOutDetailBO : billOutDetailBOS1) {

//                            QueryWrapper<ItemInfo> ct = Wrappers.query();
//                            ItemInfo itemInfo = itemInfoMapper.selectOne(ct.eq("item_code", billOutDetailBO.getItemNumber()));
                            ItemInfo itemInfo = itemInfoList.stream().filter(item -> item.getItemCode().equals(billOutDetailBO.getItemNumber())).collect(Collectors.toList()).get(0);
                            if( itemInfo.getPickTacticCode() != "标准件" && itemInfo.getPickTacticCode() != "标准件-MRP物料" && itemInfo.getPickTacticCode() != "辅料-MRP物料" && itemInfo.getPickTacticCode() != "辅料"){

                                SoDetail soDetail = new SoDetail();

                                soDetail.setBillNo(billOutDetailBO.getBillNo());
                                soDetail.setBomSplit(billOutDetailBO.getRowIndex());//行号
                                soDetail.setAllotPackDetailId(billOutDetailBO.getItemId());//物料ID
                                soDetail.setItemCode(billOutDetailBO.getItemNumber());//物料编码
                                soDetail.setItemName(billOutDetailBO.getItemName());//物料名称
                                soDetail.setSpec(billOutDetailBO.getItemModel());//规格型号
                                soDetail.setPickPackDetailId(billOutDetailBO.getAuxPropClassId());//辅助属性类别ID
                                soDetail.setDeliveryPackDetailId(billOutDetailBO.getAuxPropId());//辅助属性ID
                                soDetail.setModel(billOutDetailBO.getAuxPropName());//辅助属性
                                //批次管理
                                soDetail.setPackDescribe(billOutDetailBO.getBatchManager() == null || billOutDetailBO.getBatchManager() == false ? "0" : "1");
                                soDetail.setDetailNo(billOutDetailBO.getBatchNo());//批号
                                soDetail.setPackDetailId(billOutDetailBO.getUnitId());//基本单位ID
                                soDetail.setSoUdfDs2(billOutDetailBO.getUnitName());//单位
                                soDetail.setOrderQuantity(billOutDetailBO.getQty());//基本单位数量
                                soDetail.setPickQuantity(billOutDetailBO.getQcQty());
//                                soDetail.setAllotPackDescribe(billOutDetailBO.getPlanModeId().toString());//计划模式ID
                                soDetail.setSoUdfDs3(billOutDetailBO.getMtoNo());//计划跟踪号
                                soDetail.setMemo(billOutDetailBO.getRemark());//备注
                                soDetail.setPickPackDescribe(billOutDetailBO.getTargetBillTypeId().toString());//目标单据类型ID
                                //目标单据红蓝字
                                soDetail.setMergeNo(billOutDetailBO.getTargetBillROB() == null || billOutDetailBO.getTargetBillROB() == false ? "0" : "1");
                                soDetail.setAllotPackDescribe(billOutDetailBO.getShelfLifeDays().toString());
                                soDetail.setDeliveryPackDescribe(billOutDetailBO.getShelfLifeManager() == null || billOutDetailBO.getShelfLifeManager() == false ? "0" : "1");
                                soDetail.setAllotDetailNo(billOutDetailBO.getProductionDate());
                                soDetail.setTransRatio(1.00);
                                soDetailList.add(soDetail);
                            }

                        }
                        //新增任务
                        for (BillOutBO billOutBO : billOutBOS) {
                            SoMaster soMaster = new SoMaster();
                            soMaster.setCreateTime(DateUtils.getNowDateTimeString());
                            soMaster.setOrganizationId(86);//货主id
                            soMaster.setWareId(wareId);//仓库id
                            soMaster.setWareCode(wareMap.get(wareId).get(0).getWareCode());
                            soMaster.setWareName(wareMap.get(wareId).get(0).getWareName());
                            soMaster.setSupplierId(billOutBO.getSupplierId());//供应商id
                            soMaster.setSupplierName(billOutBO.getSupplierName()); // 供应商名称
                            soMaster.setOrderBillNo(billOutBO.getBillNo()); //订单号


                            //单据数量
                            soMaster.setSoQty(this.sumSoQty(billOutDetailBOS1, billOutBO.getBillNo()));
                            //出库数量
                            soMaster.setQcQty(this.sumQcQty(billOutDetailBOS1, billOutBO.getBillNo()));
//                            soMaster.setCreateUserName(billOutBO.getBillTypeId().toString()); //单据类型id
                            soMaster.setSoType(billOutBO.getBillTypeId()); //单据类型id
//                            soMaster.setWareCode(billOutBO.getBillTypeName());//单据类型名称
                            soMaster.setSoTypeName(billOutBO.getBillTypeName());//单据类型名称
                            //履约号
                            soMaster.setTradeNo(billOutBO.getAgreementNo());
                            soMaster.setBillNo(billOutBO.getBillNo());//单据编号
                            soMaster.setShipCode(billOutBO.getBillDate());//单据日期
                            //工业单据状态 0 - 草稿 1 - 已审核，未关联 2 - 已审批，部分关联 3 - 已审批，全部关联 生产任务单据状态 0 - 计划 5 - 确认 1 - 下达 3 - 结案 BOS单据状态 2 - 未审核 4 - 审核中 16 - 已审核
                            soMaster.setCarrierId(billOutBO.getBillStatus());//工业单据状态
                            soMaster.setIsClose(billOutBO.getBillClosed() == null || billOutBO.getBillClosed() == false ? 0 : 1);//关闭状态
                            soMaster.setOrganizationId(-1);
                            soMaster.setOrganizationName("自有");
                            soMaster.setOrganizationCode("SYS_MINE");

//                            soMaster.setCreateUserId(billOutBO.getSupplierId());//供应商ID
//                            soMaster.setOrganizationId(billOutBO.getSupplierId());//供应商ID
////                          soMaster.setSoUdfHs2(billOutBO.getSupplierName());//供应商名称
//                            soMaster.setOrganizationName(billOutBO.getSupplierName());//供应商名称


                            soMaster.setDeptId(billOutBO.getDeptId());//部门ID
                            soMaster.setDeptName(billOutBO.getDeptName());//部门名称
                            soMaster.setMemo(billOutBO.getRemark());//备注
                            soMaster.setOutUserName(billOutBO.getPlanStartDate());//计划开工日期
                            soMaster.setCustomerId(billOutBO.getCustomerId());//客户ID
                            soMaster.setCustomerName(billOutBO.getCustomerName());//客户名称
                            //新增
                            soMasters.add(soMaster);
                        }

                        //批量新增
                        this.different(billOutBOS);
                        //合并物料编码一样的单据,物料编码一样的数量++
                        List<SoDetail> soDetails = this.merge(soDetailList);
                        //批量新增 soMaster
                        soMasterService.saveBatch(soMasters);
                        //批量新增 详情
                        soDetailService.saveBatch(soDetails);
                        //执行拣货任务
//                        pickTaskService.createPickTask(null);


                    }
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    try {
                        if (response != null)
                            response.close();

                    } catch (IOException e) {
                        e.printStackTrace();
                    } finally {
                        try {
                            if (client != null)
                                client.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }

        return null;
    }


    //合并物料编码一样的单据
    public List<SoDetail> merge(List<SoDetail> soDetails) {
        Map<String, List<SoDetail>> soDetailMap = soDetails.stream().collect(Collectors.groupingBy(SoDetail::getItemCode));
        List<SoDetail> soDetailList = new ArrayList<>();
        soDetailMap.forEach((key,val)->{
            //合计数量
            double sum = val.stream().mapToDouble(SoDetail::getOrderQuantity).sum();
            SoDetail soDetail = soDetailMap.get(key).get(0);
            soDetail.setOrderQuantity(sum);
            soDetailList.add(soDetail);
        });
        return soDetailList;
    }

    public void different(List<BillOutBO> list) {

        Set<Integer> newCollect = list.stream().map(BillOutBO::getCustomerId).collect(Collectors.toSet());
        Set<Integer> oldCustomers = customerMapper.selectBatchIds(newCollect).stream().map(Customer::getCustomerId).collect(Collectors.toSet());

        Set<Integer> collect = newCollect.stream().filter(item -> !oldCustomers.contains(item)).collect(Collectors.toSet());
        List<BillOutBO> newList = list.stream().filter(item -> collect.contains(item.getCustomerId())).collect(Collectors.toList());
        List<Customer> customerList = new ArrayList<>();
        for (BillOutBO billOutBO : newList) {
            Customer customer = new Customer();
            customer.setCustomerId(billOutBO.getCustomerId());
            customer.setCustomerName(billOutBO.getCustomerName());
            customerList.add(customer);
        }
        customerService.saveBatch(customerList);
    }


    @Override
    public String outbillToErp() {

        try {
            //请求token
            MultiValueMap<String, String> stringMultiValueMap = new LinkedMultiValueMap<>();
            stringMultiValueMap.add("client_id", "KingdeeK3_Rggy_AppClient_Test");
            stringMultiValueMap.add("client_secret", "TekE%dAISMCvwk7V");
            stringMultiValueMap.add("grant_type", "client_credentials");
            String tokenUrl = "https://syecrg.sieyuan.com:44310/connect/token";
            String clientRg = HttpClient.clientRg(tokenUrl, HttpMethod.POST, stringMultiValueMap);
            JSONObject jsonObject = JSONObject.parseObject(clientRg);
            String token = jsonObject.getString("access_token");

            if (token != null) {

//                QueryWrapper<AcceptRecord> qw = Wrappers.query();
//                List<AcceptRecord> acceptRecords = acceptRecordMapper.selectList(qw.eq("is_transmit", "0"));
                QueryWrapper<SoMaster> qw = Wrappers.query();
                List<SoMaster> soMasters = soMasterMapper.selectList(qw.ne("is_transmit", "1"));
                for (SoMaster soMaster : soMasters) {

//                    if(asnMaster != null){
                    OrderToErpBO bo = new OrderToErpBO();
                    QueryWrapper<SoDetail> adqw = Wrappers.query();
                    List<OrderDetailBO> pd = new ArrayList<>();
                    List<SoDetail> asnDetails = soDetailMapper.selectList(adqw.eq("bill_no", soMaster.getBillNo()));
                    for (SoDetail soDetail : asnDetails) {
                        OrderDetailBO db = new OrderDetailBO();
                        db.setSourceBillDetailRowIndex(soDetail.getPackDetailId());
                        db.setAuxPropId(soDetail.getDeliveryPackDetailId());
                        db.setBatchNo(soDetail.getDetailNo());
                        db.setQty(0.00);
                        db.setMtoNo(soDetail.getSoUdfDs3());
                        db.setRemark(soDetail.getMemo());
                        db.setProductionDate(soDetail.getAllotDetailNo());
                        db.setShelfLifeDays(Integer.parseInt(soDetail.getAllotPackDescribe()));
//                        db.setSourceBillId(asnMaster.getOrganizationId());
                        db.setStockPlaceId(1);

//                        bo.setBillTypeId(Integer.parseInt(asnDetail.getUpperPackDescribe()));
                        pd.add(db);
                    }
//                    bo.setBillNo(soMaster.getSoMasterId().toString());
                    bo.setBillDate(new SimpleDateFormat("yyyy-MM-dd").format(new SimpleDateFormat("yyyy-MM-dd").parse(soMaster.getOutUserName())));
//                    bo.setSourceBillTypeId(soMaster.getBillType());
                    bo.setStockId(5924);
                    bo.setRemark(soMaster.getMemo());
                    bo.setDetails(pd);
                    //调用erp接口获取数据
                    CloseableHttpClient client = HttpClients.createDefault();
                    URIBuilder uriBuilder = new URIBuilder("https://syecrg.sieyuan.com:44398/api/IMBill/PushIMBill");
                    HttpPost post = new HttpPost(uriBuilder.build());
                    StringEntity myEntity = new StringEntity(JSON.toJSONString(bo), "UTF-8");// 构造请求数据
                    //                httpHeaders.add("Accept", "application/json");
                    //                httpHeaders.add("Authorization", "Bearer " + token);
                    post.setHeader("Content-Type", "application/json");
                    post.addHeader("Authorization", "Bearer " + token);
                    post.setEntity(myEntity);// 设置请求体
                    String responseContent = null; // 响应内容
                    CloseableHttpResponse response = null;
                    try {
                        response = client.execute(post);
                        System.out.println("response===>" + JSON.toJSONString(response));
                        if (response.getStatusLine().getStatusCode() == 200) {
                            //                    System.out.println("sucess");
                            //修改推送到智能货柜的数据状态  acceptRecords
                            for (SoMaster ar : soMasters) {
                                ar.setIsTransmit("1");
                                soMasterMapper.updateById(ar);
                            }
                        }
                        //                System.out.println("responseContent:" + responseContent);
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        try {
                            if (response != null)
                                response.close();

                        } catch (IOException e) {
                            e.printStackTrace();
                        } finally {
                            try {
                                if (client != null)
                                    client.close();
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
//                }

            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        return null;
    }

    @Override
    public String outbillToErpNew(String billNo) {


        try {
            //请求token
            MultiValueMap<String, String> stringMultiValueMap = new LinkedMultiValueMap<>();
            stringMultiValueMap.add("client_id", "KingdeeK3_Rggy_AppClient_Test");
            stringMultiValueMap.add("client_secret", "TekE%dAISMCvwk7V");
            stringMultiValueMap.add("grant_type", "password");
            stringMultiValueMap.add("username", "epichust");
            stringMultiValueMap.add("password", "hK@vmz0YI1e^thtB");
            String tokenUrl = "https://syecrg.sieyuan.com:44310/connect/token";
            String clientRg = HttpClient.clientRg(tokenUrl, HttpMethod.POST, stringMultiValueMap);
            JSONObject jsonObject = JSONObject.parseObject(clientRg);
            String token = jsonObject.getString("access_token");
            System.out.println(token);
            if (token != null) {
                QueryWrapper<SoMaster> amqw = Wrappers.query();
                SoMaster soMaster = soMasterMapper.selectOne(amqw.eq("bill_no", billNo));
                OrderToErpBO bo = new OrderToErpBO();
                QueryWrapper<SoDetail> adqw = Wrappers.query();
                List<OrderDetailBO> pd = new ArrayList<>();
                List<SoDetail> asnDetails = soDetailMapper.selectList(adqw.eq("bill_no", soMaster.getBillNo()));
                List<PickTask> pickTasks = pickTaskService.getListByField("so_master_id", soMaster.getSoMasterId());
                for (PickTask pickTask : pickTasks) {
                    OrderDetailBO db = new OrderDetailBO();
                    QueryWrapper<SoDetail> sdqw = Wrappers.query();
                    SoDetail soDetail = soDetailMapper.selectOne(sdqw.eq("so_detail_id", pickTask.getSoDetailId()));
                    db.setSourceBillDetailRowIndex(soDetail.getBomSplit());
                    db.setAuxPropId(soDetail.getDeliveryPackDetailId());
                    db.setBatchNo(soDetail.getDetailNo());
                    db.setQty(pickTask.getPickQuantity());
                    db.setMtoNo(soDetail.getSoUdfDs3());
                    db.setRemark(soDetail.getMemo());
                    db.setProductionDate(soDetail.getAllotDetailNo());
                    db.setShelfLifeDays(Integer.parseInt(soDetail.getAllotPackDescribe()));
//                        db.setSourceBillId(asnMaster.getOrganizationId());
                    db.setStockPlaceId(1);
//                    db.setSourceBillId(soMaster.getCheckUserId());

//                        bo.setBillTypeId(Integer.parseInt(asnDetail.getUpperPackDescribe()));
                    pd.add(db);
                }

//                bo.setBillNo(soMaster.getSoMasterId().toString());
                bo.setBillDate(new SimpleDateFormat("yyyy-MM-dd").format(new SimpleDateFormat("yyyy-MM-dd").parse(soMaster.getShipCode())));
                bo.setSourceBillTypeId(Integer.parseInt(soMaster.getCreateUserName()));
                bo.setStockId(5924);
                bo.setRemark(soMaster.getMemo());
//                Integer billTypeId = getBillTypeId(soMaster.getWareCode(), Integer.parseInt(soMaster.getCreateUserName()));
                Integer billTypeId = Integer.parseInt(asnDetails.get(0).getPickPackDescribe());
                bo.setBillTypeId(Integer.parseInt(asnDetails.get(0).getPickPackDescribe()));
                Integer categoryId = getCategoryId(billTypeId, token);
                bo.setCategoryId(categoryId);
                bo.setDetails(pd);
                //调用erp接口获取数据
                CloseableHttpClient client = HttpClients.createDefault();
                URIBuilder uriBuilder = new URIBuilder("https://syecrg.sieyuan.com:44398/api/IMBill/PushIMBill");
                HttpPost post = new HttpPost(uriBuilder.build());
                ErpBackRecord erpRecord = new ErpBackRecord();
                erpRecord.setCode(billNo);
                erpRecord.setParam(JSON.toJSONString(bo));
                StringEntity myEntity = new StringEntity(JSON.toJSONString(bo), "UTF-8");// 构造请求数据
                //                httpHeaders.add("Accept", "application/json");
                //                httpHeaders.add("Authorization", "Bearer " + token);
                post.setHeader("Content-Type", "application/json");
                post.addHeader("Authorization", "Bearer " + token);
                post.setEntity(myEntity);// 设置请求体
                String responseContent = null; // 响应内容
                CloseableHttpResponse response = null;
                try {
                    response = client.execute(post);
                    HttpEntity entity = response.getEntity();
                    InputStream content = entity.getContent();
                    String msg = inputStream2String(content);
//                    System.out.println("response===>" + JSON.toJSONString(response));
                    if (response.getStatusLine().getStatusCode() == 200) {
                        System.out.println("出库回传erp成功");
                        erpRecord.setCode("200");
                        erpRecord.setState(2);
                        erpRecord.setMsg("出库回传erp成功");
                        erpBackRecordMapper.insert(erpRecord);
                        return msg;
                    } else {
                        System.out.println("出库回传erp报错");
                        erpRecord.setCode(String.valueOf(response.getStatusLine().getStatusCode()));
                        erpRecord.setState(1);
                        erpRecord.setMsg(msg);
                        erpBackRecordMapper.insert(erpRecord);
                        System.out.println(erpRecord.getParam());
                        throw new Exception("出库回传erp报错");
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    try {
                        if (response != null)
                            response.close();

                    } catch (IOException e) {
                        e.printStackTrace();
                    } finally {
                        try {
                            if (client != null)
                                client.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }else {
                throw new Exception("token的取值为空");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }

        return null;
    }

    @Override
    public void createSoMaster2(SoData soData, CurrentUser currentUser) {
        /**
         *  新建SO单据
         */
        SoMaster soMaster = soData.getSoMaster();
        String tableName = "so_master";
        Integer nextId = validatorService.getNextId(tableName);

        String billNo = "SO" + "-" + nextId;
        Integer createUserId = currentUser.getUserId();
        String createUserName = currentUser.getUserName();
        String createTime = DateUtils.getNowDateTimeString();

        if (soData.getBillSource() == 1 || soData.getBillSource() == 3 || soData.getBillSource() == 4) {
            //状态    2-等待审核(初始化)  1-审核通过  0-审核中  -1-审核退回
            Integer state = 1;

            if (soData.getInsertType() == -2) {
                //草稿
                state = 1;
            } else if (soData.getInsertType() == 0) {
                //正式提交
                String billNo1 = soData.getSoMaster().getBillNo();
                //通过草稿提交，则需要先把草稿删掉
                if (billNo1 != null) {
                    soMasterService.deleteByBillNo(billNo1);
                }
                /**
                 * 添加审核流
                 */
                //        -1不通过  0-流转中 1-已通过
                state = caseMasterService.createCase(billNo, 3, currentUser.getUserId(), soMaster.getWareId(), soMaster.getOrganizationId());
            }

            soMaster.setCreateUserId(createUserId);
            soMaster.setCreateUserName(createUserName);
            soMaster.setCreateTime(createTime);
            soMaster.setBillNo(billNo);
            soMaster.setCaseState(state);
            soMaster.setInsertType(soData.getInsertType());
            soMaster.setBillSource(soData.getBillSource());
            soMaster.setSoStructure(soData.getSoDetails().size());
            soMaster.setSoUdfHs1("1");//标记先发配件出库单据
            soMasterService.save(soMaster);


            List<SoDetail> soDetails = soData.getSoDetails();
            for (int i = 0; i < soDetails.size(); i++) {
                String detailNo = billNo + "-" + (i + 1);
                SoDetail soDetail = soDetails.get(i);
                soDetail.setBillNo(billNo);
                soDetail.setDetailNo(detailNo);
                soDetail.setState(0);
                soDetailService.save(soDetail);
            }
        }
    }

    @Override
    public List<SoMasterDto> findList2(SoMasterCriteria criteria) {
        return soMasterMapper.findList2(criteria);
    }

    @Override
    public void createSoMaster3(SoData soData, CurrentUser currentUser) {
        /**
         *  新建SO单据
         */
        SoMaster soMaster = soData.getSoMaster();
        String tableName = "so_master";
        Integer nextId = validatorService.getNextId(tableName);

        String billNo = "SO" + "-" + nextId;
        Integer createUserId = currentUser.getUserId();
        String createUserName = currentUser.getUserName();
        String createTime = DateUtils.getNowDateTimeString();

        if (soData.getBillSource() == 1 || soData.getBillSource() == 3 || soData.getBillSource() == 4) {
            //状态    2-等待审核(初始化)  1-审核通过  0-审核中  -1-审核退回
            Integer state = 1;

            if (soData.getInsertType() == -2) {
                //草稿
                state = 1;
            } else if (soData.getInsertType() == 0) {
                //正式提交
                String billNo1 = soData.getSoMaster().getBillNo();
                //通过草稿提交，则需要先把草稿删掉
                if (billNo1 != null) {
                    soMasterService.deleteByBillNo(billNo1);
                }
                /**
                 * 添加审核流
                 */
                //        -1不通过  0-流转中 1-已通过
                state = caseMasterService.createCase(billNo, 3, currentUser.getUserId(), soMaster.getWareId(), soMaster.getOrganizationId());
            }

            soMaster.setCreateUserId(createUserId);
            soMaster.setCreateUserName(createUserName);
            soMaster.setCreateTime(createTime);
            soMaster.setBillNo(billNo);
            soMaster.setCaseState(state);
            soMaster.setInsertType(soData.getInsertType());
            soMaster.setBillSource(soData.getBillSource());
            soMaster.setSoStructure(soData.getSoDetails().size());
            soMaster.setSoUdfHs1("2");//标记先发配件出库单据
            soMasterService.save(soMaster);


            List<SoDetail> soDetails = soData.getSoDetails();
            for (int i = 0; i < soDetails.size(); i++) {
                String detailNo = billNo + "-" + (i + 1);
                SoDetail soDetail = soDetails.get(i);
                soDetail.setBillNo(billNo);
                soDetail.setDetailNo(detailNo);
                soDetail.setState(0);
                soDetailService.save(soDetail);
            }
        }
    }

    @Override
    public List<SoMasterDto> findList3(SoMasterCriteria criteria) {
        return soMasterMapper.findList3(criteria);
    }

    /**
     * 获取任务数据
     *
     * @param page
     * @return
     */
    @Override
    public List<SoMasterVo> alignList(QueryCriteria criteria) {
      return   baseMapper.alignList(criteria);
    }

    /**
     * 齐套提交
     *
     * @param soDetailVo
     */
    @Override
    public void submitQitao(SoDetailVo soDetailVo) {

        //借料项
        List<BillOutDetailBO> billOutDetailBOS = soDetailVo.getBillOutDetailBOS().stream().filter(item -> ObjectUtil.isNotEmpty(item.getNumber())).collect(Collectors.toList());
        //借料项全部数
        double sum = billOutDetailBOS.stream().mapToDouble(BillOutDetailBO::getNumber).sum();
        if (sum == 0) {
            throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR,"借料数量为空");
        }
        //全部项
        SoDetail soDetail = soDetailVo.getAll().get(0);
        Map<String,Object> soDetil = baseMapper.findByDetilId(soDetail.getSoDetailId());
        Inventory inventory = new Inventory();
        //todo 转换入库,
        this.copyInventory(inventory, soDetil);
        inventory.setQuantity(sum);
        inventoryService.save(inventory);
        //todo 判断改订单号是否库存足够
        if (this.isQitao(soDetail.getBillNo())) {
            //修改状态为已齐套
            SoMaster soMaster = soMasterService.getOne(new QueryWrapper<SoMaster>().eq("bill_no", soDetail.getBillNo()));
            soMaster.setIsVerify(1);
            soMasterService.updateById(soMaster);

        }
        //
//        setBillNo.add(soDetail.getBillNo());
        if (soDetail.getOrderQuantity() - soDetail.getPickQuantity() < sum) {
            throw new ServiceException(CommonCode.PARAMETER_ERROR,"借料数量大于差异数量");
        }
            //回传ERP
         this.pushErp(billOutDetailBOS, "123456");


    }

    public boolean isQitao(String billNo) {
        List<SoDetail> soDetailList = soDetailService.list(new QueryWrapper<SoDetail>().in("bill_no", billNo));
        Set<String> itemCodeSet = soDetailList.stream().map(SoDetail::getItemCode).collect(Collectors.toSet());
        List<Inventory> inventoryList = inventoryService.list(new QueryWrapper<Inventory>().in("item_code", itemCodeSet));
        for (SoDetail soDetail : soDetailList) {
            // //货主id 88货主Id默认为 -1 自有, code SYS_MINE
            soDetail.setMarginQty(soDetailService.putNumber(inventoryList, soDetail.getItemCode(), -1));
        }
        List<SoDetail> soDetails = soDetailService.lendDetail(soDetailList);
        return soDetails.size() == soDetailList.size();

    }

    public void copyInventory(Inventory inventory, Map<String, Object> map) {
        inventory.setWareId(Integer.valueOf(map.get("wareId").toString()));
        inventory.setWareName(map.get("wareName").toString());
        inventory.setOrganizationId(Integer.valueOf(map.get("organizationId").toString()));
        inventory.setOrganizationName(map.get("organizationName").toString());
        inventory.setItemCode(map.get("itemCode").toString());
        inventory.setItemName(map.get("itemName").toString());
        inventory.setBillNo(map.get("billNo").toString());
    }

    public static void main(String[] args) throws Exception {

        //请求token
        System.out.println("请求token");
        MultiValueMap<String, String> stringMultiValueMap = new LinkedMultiValueMap<>();
        stringMultiValueMap.add("client_id", "KingdeeK3_Rggytest_EpichustClient");
        stringMultiValueMap.add("client_secret", "TekE%dAISMCvwk7V");
        stringMultiValueMap.add("grant_type", "client_credentials");
        String tokenUrl = "https://identityserver:44310/connect/token";
        String clientRg = HttpClient.clientRg(tokenUrl, HttpMethod.POST, stringMultiValueMap);
        JSONObject jsonObject = JSONObject.parseObject(clientRg);
        String token = jsonObject.getString("access_token");
        System.out.println("token" + token);

        if (token != null) {

//                for(int i = 1 ; i<=27; i++){
            Map<String, String> map1 = new HashMap<>();
            map1.put("dateFrom", "2022-05-25");
//                    map1.put("pageSize",10000);

            //调用erp接口获取数据
            CloseableHttpClient client = HttpClients.createDefault();
            URIBuilder uriBuilder = new URIBuilder("http://10.18.3.10:30001/api/Epichust/GetAllIMOutSourceBills");
            HttpPost post = new HttpPost(uriBuilder.build());
            StringEntity myEntity = new StringEntity(JSON.toJSONString(map1), "UTF-8");// 构造请求数据
            post.setHeader("Content-Type", "application/json");
            post.addHeader("Authorization", "Bearer " + token);
            post.setEntity(myEntity);// 设置请求体
            String responseContent = null; // 响应内容
            CloseableHttpResponse response = null;
            try {
                response = client.execute(post);
                HttpEntity entity = response.getEntity();
                if (response.getStatusLine().getStatusCode() == 200) {
                    String content = EntityUtils.toString(entity, "UTF-8");
                    System.out.println(content);
//                            ItemResponseBO itemResponseBO = JSONArray.parseObject(content, ItemResponseBO.class);
//                            String it = itemResponseBO.getList();
//                            List<ItemErpBO> itemErpBOS = (List<ItemErpBO>) JSON
//                                    .parseArray(it, ItemErpBO.class);


                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    if (response != null)
                        response.close();

                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    try {
                        if (client != null)
                            client.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
//                }


        }
    }

    public Integer getCategoryId(Integer billTypeId, String token) {
        String url;
        if (billTypeId == 10) {
            url = "https://syecrg.sieyuan.com:44398/api/Item/GetAllItems/3012";
        } else if (billTypeId == 24) {
            url = "https://syecrg.sieyuan.com:44398/api/Item/GetAllItems/3009";
        } else if (billTypeId == 29) {
            url = "https://syecrg.sieyuan.com:44398/api/Item/GetAllItems/3011";
        } else if (billTypeId == 41) {
            url = "https://syecrg.sieyuan.com:44398/api/SubMsg/GetAllSubMsgs/10027";
        } else {
            url = null;
        }
        if (url != null) {
            try {
                //调用erp接口获取数据
                HttpHeaders httpHeaders = new HttpHeaders();
                httpHeaders.add("Accept", "application/json");
                httpHeaders.add("Authorization", "Bearer " + token);
                String result = HttpClient.getRequest(url, null, httpHeaders);
                JSONArray jsonArray = JSONArray.parseArray(result);
                List<CustInfoBO> di = JSONObject.parseArray(jsonArray.toJSONString(), CustInfoBO.class);
                if (di.size() != 0) {
                    return di.get(0).getId();
                }
                return null;
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        } else {
            return null;
        }
    }

    public static String inputStream2String(InputStream is) throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        int i = -1;
        while ((i = is.read()) != -1) {
            baos.write(i);
        }
        return baos.toString();
    }

    public void pushErp(List<BillOutDetailBO> billOutDetailBOS, String billNo)  {
        //获取token
        String token = this.requestToken();

        if (ObjectUtil.isNotEmpty(token)) {
            OrderToErpBO orderToErpBO = new OrderToErpBO();
            //时间
            orderToErpBO.setBillNo(billNo);
            orderToErpBO.setBillTypeId(24);
            orderToErpBO.setCategoryId(27718);
            orderToErpBO.setSourceBillTypeId(88);
            orderToErpBO.setStockId(5924);
            orderToErpBO.setRob(true);

            orderToErpBO.setDetails(replase(billOutDetailBOS));
            orderToErpBO.setBillNo(billNo);

            try {
                //调用erp接口获取数据
                CloseableHttpClient client = HttpClients.createDefault();
                URIBuilder uriBuilder = new URIBuilder("https://syecrg.sieyuan.com:44398/api/IMBill/PushIMBill");
                HttpPost post = new HttpPost(uriBuilder.build());
                ErpBackRecord erpRecord = new ErpBackRecord();
                erpRecord.setCode(billNo);
                erpRecord.setParam(JSON.toJSONString(orderToErpBO));
                StringEntity myEntity = new StringEntity(JSON.toJSONString(orderToErpBO), "UTF-8");// 构造请求数据
                //                httpHeaders.add("Accept", "application/json");
                //                httpHeaders.add("Authorization", "Bearer " + token);
                post.setHeader("Content-Type", "application/json");
                post.addHeader("Authorization", "Bearer " + token);
                post.setEntity(myEntity);// 设置请求体
                String responseContent = null; // 响应内容
                CloseableHttpResponse response = null;

                response = client.execute(post);
                HttpEntity entity = response.getEntity();
                InputStream content = entity.getContent();
                String msg = inputStream2String(content);
//                    System.out.println("response===>" + JSON.toJSONString(response));
                //todo
                if (response.getStatusLine().getStatusCode() == 200) {
                    System.out.println("出库回传erp成功");
                    erpRecord.setCode("200");
                    erpRecord.setState(2);
                    erpRecord.setMsg("出库回传erp成功");
                    erpBackRecordMapper.insert(erpRecord);
                } else {
                    System.out.println("出库回传erp报错");

                    erpRecord.setCode(String.valueOf(response.getStatusLine().getStatusCode()));
                    erpRecord.setState(1);
                    erpRecord.setMsg(msg);
                    erpBackRecordMapper.insert(erpRecord);
                    throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR,msg);
                }
            } catch (ClientProtocolException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (URISyntaxException e) {
                e.printStackTrace();
            }


        }
    }

    public List<OrderDetailBO> replase(  List<BillOutDetailBO> outDetail) {
        List<OrderDetailBO> orderDetailBOList = new ArrayList<>();
        outDetail.forEach(item->{

            OrderDetailBO orderDetailBO = new OrderDetailBO();
            BeanUtils.copyProperties(item, orderDetailBO);
            orderDetailBO.setSourceBillDetailRowIndex(item.getRowIndex());//行号

            orderDetailBO.setSourceBillId(item.getSourceBillId());//源单id
            orderDetailBO.setAuxPropId(item.getAuxPropId());//辅助属性ID
            //批号
            orderDetailBO.setBatchNo(item.getBatchNo()); //
            orderDetailBO.setQty(item.getNumber());
            orderDetailBO.setMtoNo(item.getMtoNo());
            orderDetailBO.setRemark(item.getRemark());
            orderDetailBO.setTargetBillROB(true);
            orderDetailBOList.add(orderDetailBO);

        });
        return orderDetailBOList;

    } //单据明细

    public String requestToken() {
        //请求token
        MultiValueMap<String, String> stringMultiValueMap = new LinkedMultiValueMap<>();
        stringMultiValueMap.add("client_id", "KingdeeK3_Rggy_AppClient_Test");
        stringMultiValueMap.add("client_secret", "TekE%dAISMCvwk7V");
        stringMultiValueMap.add("grant_type", "password");
        stringMultiValueMap.add("username", "epichust");
        stringMultiValueMap.add("password", "hK@vmz0YI1e^thtB");
        String tokenUrl = "https://syecrg.sieyuan.com:44310/connect/token";
        String clientRg = null;
        try {
            clientRg = HttpClient.clientRg(tokenUrl, HttpMethod.POST, stringMultiValueMap);
        } catch (Exception e) {
            e.printStackTrace();
        }
        JSONObject jsonObject = JSONObject.parseObject(clientRg);
        String token = jsonObject.getString("access_token");
        return token;
    }
}
